/*
    1、保留了JS的基本方法定义方式
    2、在原有的方法定义方式上，扩展了方法的功能限制
        + 方法参数限制
            方法在执行时可以传入的参数的数量类型
        + 方法返回值限制
            描述当前方法执行后是否存在返回值且返回的数据类型
        + 方法执行结果限制
            随着方法返回值限制发生变化
*/
function showA()
{
    console.log("showA");
}
var showB = function()
{
    console.log("showB");
}

// 方法定义完成后，直接就限制了方法在后续执行时
// 能够传入的参数数量
// showA(1,2,3);
function printArg1(arg1,arg2,arg3){
    console.log(arg1,arg2,arg3);
}
printArg1(1,2,3);
// 方法定义后，当定义了形参，方法的形参类型也会直接被限制
//  1、定义时未指定==TS默认认为形参为 any 类型
//  2、定义时通过 形参:类型 方式描述每个形参的固定数据类型
function printArg2(arg1:string,arg2:boolean,arg3:number[]){
    console.log(arg1,arg2,arg3);
}
printArg2("字符串",false,[1,2,3,4]);

enum aa {
    a=1,
    b=2
}
function printArg3(arg1:string,arg2:aa,arg3:any){
    console.log(arg1,arg2,arg3);
}
printArg3("字符串",aa.a,1234);
printArg3("字符串",aa.a,false);

// 方法定义时的参数关键字
//      关键字 ? 描述当前形参为可传参数
//              function 方法名(参数名?:类型)
//            ? 必须连续，且只能定义在最后的形参上
//      关键字 = 描述方法形参具有的相关默认值
//              function 方法名(参数名:类型=默认值)
//              一旦形参定义了默认值，该形参本身就是可选参数
//              遵循可选参数的定义规则
//              默认值只有两种情况可取，参数未传或者传入undefined
function printArg4(arg1:string,arg2?:string){
    if(arg2==undefined){
        arg2 = "aa";
    }
    arg1.replace("c",arg2);
}
// 方法定义的形参和方法调用的实参，存在位置对应关系
printArg4("abcdef");

// function printArg5(
//     arg1:string,
//     arg2?:string,
//     arg3:string,
//     arg4:string
// ){

// }

// printArg5( arg1,arg2 [,arg3[,arg4]] );
function printArg5(
    arg1:string,
    arg2:string,
    arg3?:string,
    arg4?:string
){

}
printArg5("a","b","c");
printArg5("a","b");

// jquery 的 jQuery.post(url, [data], [callback], [type])
function post(
    url:string,
    params?:any,
    fun?:any,
    type?:string
){
    if(typeof fun != "function"){
        type = fun;
        fun = params;
        params = null;
    }
    // ……
    console.log("url:",url);
    console.log("params:",params);
    console.log("fun:",fun);
    console.log("type:",type);

}
post("http://???",function() {
    
},"json")

function  printArg6(
    arg1:number,
    arg2:number,
    arg3:number=1111
) {
    console.log(arg1,arg2,arg3);
}
printArg6(1,2,3);
printArg6(1,2);

function  printArg7(
    arg1:number,
    arg2:number=1111,
    arg3:number
) {
    console.log(arg1,arg2,arg3);
}
printArg7(1,undefined,2);

function  printArg8(
    arg1?:number,
    arg2:number=1111,
    arg3?:number
) {
    console.log(arg1,arg2,arg3);
}

// 方法的返回值可以方法定义时，方法声明后以:进行描述
// function 方法名称():是否存在返回值且返回值的类型{}
function returnFun1():string
{
    return "字符串";
}
returnFun1();

// TS 对 JS 中 void 进行类型定义
// void 类型描述方法无返回值
// 在方法的声明后面 以 :void 描述当前方法无返回值
// 方法定义时 如果没有在方法声明后定义返回值修饰，默认就是 void
//   同时也会限制 当前方法的方法体 不能定义 return 数据; 表达式
function returnFun2():void
{
    // return 123;
}

function returnFun3(flag:boolean):void
{   
    if(flag){
        return;
    }
    console.log("flag:",flag);
}

// 1、如果方法定义时要求存在返回值，
//    方法中的所有分支节点都必须存在返回结果
function returnFun4(flag:boolean):string{
    if(flag){
        return "真";
    }else{
        return "假";
    }
}

function returnFun5():string {
    try {
        // ……
        console.log("正常流程");
        return "结果";
    } catch (error) {
        throw error; // 错误抛出行为，描述当前方法运行错误，无需返回值
    }
}

// never 描述程序不会存在关于返回的功能
function returnFun6():never {
    throw new Error("运行错误");
}
